/*
 ************************************************************************************************
 *                                                                                              *
 *  OSA cooperative RTOS for Microchip PIC-controllers: PIC10/12/16/18/24/dsPIC                 *
 *                                                                                              *
 *  URL:        http://wiki.pic24.ru/doku.php/en/osa/ref/intro                                  *
 *              http://picosa.narod.ru                                                          *
 *                                                                                              *
 *----------------------------------------------------------------------------------------------*
 *                                                                                              *
 *  File:       osa_queue.h                                                                     *
 *                                                                                              *
 *  Compilers:  HT-PICC STD                                                                     *
 *              HT-PICC18 STD                                                                   *
 *              Microchip C18                                                                   *
 *              Microchip C30                                                                   *
 *                                                                                              *
 *  Programmer: Timofeev Victor                                                                 *
 *              osa@pic24.ru, testerplus@mail.ru                                                *
 *                                                                                              *
 *  Definition: Services for work with queue of pointers to messages                            *
 *                                                                                              *
 *                                                                                              *
 ************************************************************************************************
 */


/************************************************************************************************
 *                                                                                              *
 *                              Q U E U E   O F   M E S S A G E S                               *
 *                                                                                              *
 ************************************************************************************************/


#if defined(OS_ENABLE_INT_QUEUE)

    #define __OS_QUEUE_DI()       {_OS_temp = OS_DI();}
    #define __OS_QUEUE_RI()       {OS_RI(_OS_temp);}

#else

    #define __OS_QUEUE_DI()
    #define __OS_QUEUE_RI()

#endif



//------------------------------------------------------------------------------
#ifdef OS_ENABLE_QUEUE
//------------------------------------------------------------------------------

extern void     _OS_Queue_Send (OST_QUEUE *pQueue, OST_MSG Msg);
extern OST_MSG  _OS_GetQueue  (OST_QUEUE *pQueue);


//------------------------------------------------------------------------------
// Create queue

#define OS_Queue_Create(queue, buffer, size)             \
    {                                                    \
        __OS_QUEUE_DI();                                 \
        (queue).Q.cSize = size;                          \
        (queue).Q.cBegin = 0;                            \
        (queue).Q.cFilled = 0;                           \
        (queue).pMsg = (OST_MSG*)buffer;                 \
        __OS_QUEUE_RI();                                 \
    }

//------------------------------------------------------------------------------
// Check for any message present in queue

#define OS_Queue_Check(queue)        ((queue).Q.cFilled)

//------------------------------------------------------------------------------
// Check for queue is full

#define OS_Queue_IsFull(queue)       ((queue).Q.cFilled == (queue).Q.cSize)

//------------------------------------------------------------------------------
// Check for free room in queue

#define OS_Queue_IsFree(queue)       ((queue).Q.cFilled ^ (queue).Q.cSize)


//------------------------------------------------------------------------------
// Clear queue

#define OS_Queue_Clear(squeue)        { (queue).Q.cFilled = 0; }

//------------------------------------------------------------------------------
// Send message via queue. If queue full then wait for free place


#define OS_Queue_Send(queue, value)                                     \
    {                                                                   \
        if (OS_Queue_IsFull(queue))                                     \
        {                                                               \
            _OS_WAIT_EVENT(OS_Queue_IsFree(queue));                     \
        }                                                               \
        _OS_Queue_Send(&(queue), value);                                \
    }                                                                   \


//------------------------------------------------------------------------------
// Send message via queue. If queue full then wait for free place. Exit if timeout expired.

#define OS_Queue_Send_TO(queue, value, timeout)                         \
    {                                                                   \
        OS_Flags.bTimeout = 0;                                          \
        if (OS_Queue_IsFull(queue))                                     \
        {                                                               \
            _OS_WAIT_EVENT_TIMEOUT(OS_Queue_IsFree(queue), timeout);    \
        }                                                               \
        if (!OS_IsTimeout()) {                                          \
            _OS_Queue_Send(&(queue), value);                            \
        }                                                               \
    }

//------------------------------------------------------------------------------
// Send message via queue. If queue is full then most rearly message will be pushed out.

#define OS_Queue_Send_Now(queue, value)                                 \
    {                                                                   \
        _OS_Queue_Send(&(queue), value);                                \
    }


//------------------------------------------------------------------------------
// Send message via queue from interrupt. If queue is full then most rearly message will be pushed out.

#if defined(OS_ENABLE_INT_QUEUE)

    extern void _OS_IntSendQueue (OST_QUEUE *pQueue, OST_MSG Msg);

    #define OS_Queue_Send_I(queue, value)                               \
        {                                                               \
            _OS_IntSendQueue(&(queue), value);                          \
        }

#endif

//------------------------------------------------------------------------------
// Wait message from queue. After accepting message will be deleted from queue.

#define OS_Queue_Wait(queue, os_msg_type_var)                           \
    {                                                                   \
        _OS_WAIT_EVENT(OS_Queue_Check(queue));                          \
        OS_Queue_Accept(queue,os_msg_type_var)                          \
    }

//------------------------------------------------------------------------------
// Wait message from queue. After accepting message will be deleted from queue. Exit if timeout expired.

#define OS_Queue_Wait_TO(queue, os_msg_type_var, timeout)               \
    {                                                                   \
        _OS_WAIT_EVENT_TIMEOUT(OS_Queue_Check(queue), timeout);         \
        if (!OS_IsTimeout())                                            \
            OS_Queue_Accept(queue,os_msg_type_var)                      \
    }

//------------------------------------------------------------------------------
//
#define OS_Queue_Accept(queue,os_msg_type_var)                          \
    {                                                                   \
        __OS_QUEUE_DI();                                                \
        os_msg_type_var = _OS_GetQueue(&(queue));                       \
        __OS_QUEUE_RI();                                                \
    }                                                                   \



//------------------------------------------------------------------------------
#endif      // OS_ENABLE_QUEUE
//------------------------------------------------------------------------------
















